
package dao.padrao;

import dao.UsuarioDAO;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;

/**
 * @param <T> Entidade
 * @param <PK> Tipo de dado do ID
 *
 */
public class GenericDAO<T, PK> implements InterfaceDAO<T, PK> {

    private EntityManager entityManager;

    /**
     * Construtor unico
     */
    public GenericDAO() {
        this.entityManager = getEntityManager();
    }

    /**
     *
     * @return Retorna o EntityManager configurado no persistence.xml
     */
    @Override
    public EntityManager getEntityManager() {
        EntityManagerFactory emf;
        emf = Persistence.createEntityManagerFactory("ProjetoIntegradorPU");
        return emf.createEntityManager();
    }

    /**
     *
     * @param classe Classe a ser utilizada na busca por primary key
     * @param pk Passar a chave primaria (ID)
     * @return Retorna o objeto pesquisado
     */
    @Override
    public T buscaID(Class<T> classe, PK pk) {
        try {
            return entityManager.find(classe, pk);
        } catch (NoResultException e) {
            Logger.getLogger(GenericDAO.class.getName()).log(Level.SEVERE, null, e);
            return null;
        }
    }

    /**
     *
     * @param entity Entidade a ser utilizada
     * @return Retorna TRUE se o cadastro foi atualizado no banco e FALSE se não
     * foi possivel cadastrar
     */
    @Override
    public boolean atualizar(T entity) {
        boolean estate = false;
        try {
            entityManager.getTransaction().begin();
            entityManager.merge(entity);
            entityManager.flush();
            entityManager.getTransaction().commit();
            estate = true;
        } catch (Exception e) {
            Logger.getLogger(UsuarioDAO.class.getName()).log(Level.SEVERE, null, e);
        }
        return estate;
    }

    /**
     *
     * @param entity Entidade a ser utilizada
     * @return Retorna o objeto gravado no banco de dados
     */
    @Override
    public T salvar(T entity) {
        T saved = null;
        try {
            entityManager.getTransaction().begin();
            saved = entityManager.merge(entity);
            entityManager.flush();
            entityManager.getTransaction().commit();
            return saved;
        } catch (Exception e) {
            Logger.getLogger(UsuarioDAO.class.getName()).log(Level.SEVERE, null, e);
        }
        return saved;
    }

    /**
     *
     * @param entity Entidade a ser utilizada
     * @return Retorna TRUE se a deleção persistiu no banco e FALSE se não foi
     * possivel excluir
     */
    @Override
    public boolean deletar(T entity) {
        boolean estate = false;
        try {
            entityManager.getTransaction().begin();
            entityManager.remove(entity);
            entityManager.flush();
            entityManager.getTransaction().commit();
            estate = true;
        } catch (Exception e) {
            Logger.getLogger(UsuarioDAO.class.getName()).log(Level.SEVERE, null, e);
        }
        return estate;
    }

    /**
     *
     * @param classe Classe a ser utilizada na busca
     * @return Rertona uma lista de todos os resultados da classe informada como
     * parametro
     */
    @Override
    public List<T> buscar(Class<T> classe) {
        return entityManager.createQuery("select o from " + classe.getSimpleName() + " o").getResultList();
    }
}
